package models.login
{
    import flash.external.ExternalInterface;
    import flash.utils.getTimer;
    
    public class JSPort
    {
        public static const PUT:String= "PUT";
        public static const POST:String= "POST";
        public static const GET:String= "GET";
        public static const DELETE:String= "DELETE";
        private static var _instance:JSPort;
        public static function get instance():JSPort { return _instance||=new JSPort; }
        
        
        public function JSPort()
        {
            trace("JSPort.JSPort()",ExternalInterface.available,ExternalInterface.objectID);
            ExternalInterface.addCallback("callback",backFunc);
            ExternalInterface.addCallback("directback",getobj);
            ExternalInterface.addCallback("successBack",successBack);
            ExternalInterface.addCallback("errorBack",errorBack);
//			defineFunc("haha123","function () { return 123}")
//			callFunc("haha123")
            initExJs();
        }
        private function initExJs():void
        {
            evalJs("function getMovie() {	return document.getElementById('" +ExternalInterface.objectID +"'); }")
//			evalJs("function request(route, className, objectId, method, dataObject,t) {AV._request(route,className,objectId,method,dataObject).then(function (obj){getMovie().successBack(t,obj);},function (error){	getMovie().errorBack(t,error);})};");
//			evalJs("function fetchUser(obj){var user = AV.User._currentUser = AV.Object._create('_User');user._finishFetch(obj);}"); 
        
        }
        public function callFunc(name:String,...params):void
        {
            var a:Array = [name].concat(params);
            var o:Object = ExternalInterface.call.apply(this,a);
        }
        public function evalCallback(body:String):void
        {
            evalJs("getMovie().directback(" +body+")");
        }
        public function callFunc$func(jsStr:String,...args):void
        {
            var t:String =  (getTimer()+Math.random()).toFixed(2);
            CALLBACK_MAP["callbackFunc"][t]= args;
            var a:Array  = jsStr.split("$func");
            var str:String = "";
            a.forEach(function (item:String,index:int,arr:Array):void{
                str += item;
                if(index != arr.length-1){
                    str+=factory(index)
                }
            });
            trace("JSPort.callFunc$func(jsStr, args)",str);
            evalJs(str);
            function factory (i:int):String{
                return "function (){var t="+t+";getMovie().directback(t,"+i+",[].slice.call(arguments))}"
            }
        
        
//			callFunc.apply(this,[name].concat(args,t));
        }		
        public function callFuncWithBack(name:String,callback:Function,...args):void
        {
            var t:String =  (getTimer()+Math.random()).toFixed(2);
            CALLBACK_MAP["callback"][t]= callback
            callFunc.apply(this,[name].concat(args,t));
        }
        public function request(route:String, className:String, objectId:String, method:String, dataObject:Object,success:Function,error:Function):void
        {
            callFuncWithSuccAndError("request",success,error,route, className, objectId, method, dataObject);
        }
        public function callFuncWithSuccAndError(name:String,success:Function,error:Function,...args):void
        {
            var t:String =  (getTimer()+Math.random()).toFixed(2);
            CALLBACK_MAP["successBack"][t]= success
            CALLBACK_MAP["errorBack"][t]= error
            callFunc.apply(this,[name].concat(args,t));
        }
        public function evalJs(body:String):void
        {
            callFunc("eval",body);
        }
        public function defineFunc(name:String,functionbody:String):void
        {
            callFunc("eval","var "+name+" =" +functionbody);
        }
        private const CALLBACK_MAP:Object = {
                callback:{},
                callbackFunc:{},
                successBack:{},
                errorBack:{}
            };
        public function getobj(...args):void
        {
            trace("JSPort.getobj(args)",args);
            callbackhandle("callbackFunc",args)
        }
        public function backFunc(...args):void
        {
            trace("JSPort.backFunc(args)",args);
//			CALLBACK_MAP["callback"][args.shift()](args);
            callbackhandle("callback",args)
        }
        public function successBack(...args):void
        {
            trace("JSPort.successBack(args)",args);
//			CALLBACK_MAP["successBack"][args.shift()](args);
            callbackhandle("successBack",args)
        }
        public function errorBack(...args):void
        {
            trace("JSPort.errorBack(args)",args);
//			CALLBACK_MAP["errorBack"][args.shift()](args);
            callbackhandle("errorBack",args)
        }
        private function callbackhandle(name:String,args:Array):void
        {
            trace
                var obj:Object = CALLBACK_MAP[name];
            if(args && args.length)
            {
                var t:String= args.shift()
                var call:Object= obj[t];
                if(call)
                {
                    if(call is Function){
                        trace("JSPort.callbackhandle",JSON.stringify(args));
                        call.apply(this,args);
                    }
                    else{
                        for  (var i in call) 
                        {
                            call[i].apply(null,args[args.length-1]);
                        }
                    }
                    delete obj[t];
                    
                }
            }
        }
    }
}

